﻿﻿using LightWadf.Configuration;
using LightWadf.Util;
using NLog;
using System;
using System.Configuration;
using System.Runtime.Caching;
using System.Web;

namespace LightWadf.Handler
{
    public class HandlerDispatcher : IHttpHandler
    {
        private ObjectCache cache = MemoryCache.Default;

        public bool IsReusable
        {
            get
            {
                return true;
            }
        }

        public void ProcessRequest(HttpContext context)
        {
            try
            {
                var time = DateTime.Now;
                LogUtility.Trace(string.Format("LightWadf 接收到 {0} 请求", context.Request.Path));
                var dif = (DateTime.Now - time).TotalMilliseconds;

                ICustomHttpHandler handler = null;
                // 通过 cookie 中的 lwend 值来判断客户端身份
                HttpCookie cookie = context.Request.Cookies["lwend"];
                string key = null;
                if (cookie != null)
                {
                    key = cookie.Value;
                }
                // 若 lwend 值存在，则从缓存中获取处理器
                if (!string.IsNullOrEmpty(key) && this.cache.Contains(key))
                {
                    LogUtility.Trace(string.Format("请求 {1} 分发给 key 为 {0} 的 DefaultHandler", key, context.Request.Path));

                    handler = this.cache.Get(key) as ICustomHttpHandler;
                }
                // 若处理器为空，可能 lwend 不存在，可能是缓存数据过期
                if (handler == null)
                {
                    key = Guid.NewGuid().ToString();
                    cookie = new HttpCookie("lwend");
                    cookie.Value = key;
                    cookie.Expires = DateTime.Now.Add(Utility.GlobalConfiguration.HandlerSlidingExpiration);
                    context.Response.Cookies.Add(cookie);
                    handler = new DefaultHandler();

                    LogUtility.Trace(string.Format("请求分发给 key 为 {0} 的 DefaultHandler", key));

                    CacheItemPolicy policy = new CacheItemPolicy();
                    // 如果数分钟内该会话没有再次发起请求，则释放 Handler
                    policy.SlidingExpiration = Utility.GlobalConfiguration.HandlerSlidingExpiration;
                    this.cache.Set(key, handler, policy);
                }
                handler.ProcessRequest(context);
                LogUtility.Trace(string.Format("{0} 请求处理完毕", context.Request.Path));
            }
            catch (Exception e)
            {
                LogUtility.Fatal(e, string.Format("处理 {0} 请求时，DefaultHandler 异常退出", context.Request.Path));
            }
        }
    }
}
